package com.ctsi.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctsi.core.common.entity.LoginUser;
import com.ctsi.core.common.enums.StatusType;
import com.ctsi.core.common.exception.MarsException;
import com.ctsi.core.common.exception.ServiceException;
import com.ctsi.core.common.node.LoginMenuTreeNode;
import com.ctsi.core.common.node.Meta;
import com.ctsi.core.common.util.$;
import com.ctsi.core.common.util.StringPool;
import com.ctsi.core.web.checker.AdminUserChecker;
import com.ctsi.core.web.enums.MenuOpenTypeEnum;
import com.ctsi.core.web.enums.MenuTypeEnum;
import com.ctsi.core.web.enums.MenuWeightEnum;
import com.ctsi.core.web.enums.YesOrNotEnum;
import com.ctsi.system.constant.SysConstant;
import com.ctsi.system.entity.Menu;
import com.ctsi.system.entity.User;
import com.ctsi.system.entity.ZsjUser;
import com.ctsi.system.enums.SystemExceptionEnum;
import com.ctsi.system.mapper.MenuMapper;
import com.ctsi.system.service.*;
import com.ctsi.system.vo.MenuResVO;
import com.ctsi.system.vo.MenuTreeResVO;
import com.ctsi.uaa.enums.UserType;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统菜单表 服务实现类
 * </p>
 *
 * @author wang xiao xiang
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

	@Autowired
	private IUserRoleService userRoleService;
	@Autowired
	private IRoleMenuService roleMenuService;
	@Autowired
	private IUserService userService;
	@Autowired
	private AdminUserChecker adminUserChecker;
	@Autowired
	private IZsjUserService zsjUserService;

	@Override
	public List<String> getLoginPermissions(Long userId,Integer userType) {

		List<Long> roleIdList = userRoleService.getUserRoleIdList(userId,userType);
		if ($.isNotEmpty(roleIdList)) {
			// 查询菜单列表
			List<Long> menuIdList = roleMenuService.getRoleMenuIdList(roleIdList);
			if ($.isNotEmpty(menuIdList)) {
				// 根据菜单ID查询按钮列表
				return this.list(Wrappers.<Menu>query().lambda().in(Menu::getId, menuIdList)
						.eq(Menu::getType, MenuTypeEnum.BUTTON.getCode())
						.eq(Menu::getStatus, StatusType.ENABLE.getCode()))
						.stream().map(Menu::getPermission).collect(Collectors.toList());
			}
		}
		return CollectionUtil.newArrayList();
	}

	@Override
	public List<String> getUserMenuAppCodeList(Long userId,Integer userType) {
		// 查询权限列表
		List<Long> roleIdList = userRoleService.getUserRoleIdList(userId,userType);

		if ($.isNotEmpty(roleIdList)) {
			// 查询菜单列表
			List<Long> menuIdList = roleMenuService.getRoleMenuIdList(roleIdList);

			if ($.isNotEmpty(menuIdList)) {
				// 查询应用列表
				return this.list(Wrappers.<Menu>query().lambda()
						.in(Menu::getId, menuIdList)
						.eq(Menu::getStatus, StatusType.ENABLE.getCode()))
						.stream().map(Menu::getApplication).collect(Collectors.toList());
			}
		}
		return CollectionUtil.newArrayList();
	}


	@Override
	public List<LoginMenuTreeNode> getLoginMenusAntDesign(Long userId, String appCode,Integer userType) {
		List<Menu> menuList;
		//如果是超级管理员则展示所有系统权重菜单，不能展示业务权重菜单
		User user = new User();
		Integer adminType;
		switch(UserType.valueOf(userType)){
			case SYSTEM:
				user = userService.getById(userId);
				break;
			case TELECOM:
				ZsjUser zsjUser = zsjUserService.getById(userId);
				user.setId(zsjUser.getStaffId());
				user.setName(zsjUser.getStaffName());
				user.setAccount(zsjUser.getStaffAccount());
				break;
			default:
				throw new MarsException(SysConstant.NOT_SUPPORT_USERTYPE);
		}

		LambdaQueryWrapper<Menu> queryWrapper = Wrappers.lambdaQuery();

		if (adminUserChecker.hasModifyPermission($.copy(user, LoginUser.class))) {
			//查询权重不为业务权重的且类型不是按钮的
			queryWrapper.eq(Menu::getStatus, StatusType.ENABLE.getCode())
					.eq(Menu::getApplication, appCode)
					.notIn(Menu::getType, MenuTypeEnum.BUTTON.getCode())
					.notIn(Menu::getWeight, MenuWeightEnum.DEFAULT_WEIGHT.getCode())
					.orderByAsc(Menu::getSort);
		} else {
			//非超级管理员则获取自己角色所拥有的菜单集合
			List<Long> roleIdList = userRoleService.getUserRoleIdList(userId, userType);
			if (ObjectUtil.isNotEmpty(roleIdList)) {
				List<Long> menuIdList = roleMenuService.getRoleMenuIdList(roleIdList);
				if (ObjectUtil.isNotEmpty(menuIdList)) {
					queryWrapper.in(Menu::getId, menuIdList)
							.eq(Menu::getStatus, StatusType.ENABLE.getCode())
							.eq(Menu::getApplication, appCode)
							.notIn(Menu::getType, MenuTypeEnum.BUTTON.getCode())
							.orderByAsc(Menu::getSort);

				} else {
					//如果角色的菜单为空，则查不到菜单
					return CollectionUtil.newArrayList();
				}
			} else {
				//如果角色为空，则根本没菜单
				return CollectionUtil.newArrayList();
			}
		}
		//查询列表
		menuList = this.list(queryWrapper);
		//转换成登录菜单
		return this.convertSysMenuToLoginMenu(menuList);
	}

	private List<LoginMenuTreeNode> convertSysMenuToLoginMenu(List<Menu> menuList) {
		return menuList.stream().map(menu -> {
			LoginMenuTreeNode loginMenuTreeNode = $.copy(menu, LoginMenuTreeNode.class);
			if ($.isEmpty(loginMenuTreeNode)) {
				throw new ServiceException("菜单数据为空！");
			}
			loginMenuTreeNode.setName(menu.getCode());
			loginMenuTreeNode.setPath(menu.getRouter());
			Meta meta = new Meta();
			meta.setIcon(menu.getIcon());
			meta.setTitle(menu.getName());
			meta.setLink(menu.getLink());
			if (menu.getType() == 1 && $.isNotEmpty(menu.getBadge())) {
				meta.setBadge(menu.getBadge());
			}
			// 是否可见
			meta.setShow(!YesOrNotEnum.N.getCode().equals(menu.getVisible()));
			// 设置的首页，默认打开此链接
			loginMenuTreeNode.setRedirect(menu.getRedirect());
			//是否是外链
			if (MenuOpenTypeEnum.OUTER.getCode().equals(menu.getOpenType())) {
				//打开外链
				meta.setTarget("_blank");
				loginMenuTreeNode.setPath(menu.getLink());
				loginMenuTreeNode.setRedirect(menu.getLink());
			}
			loginMenuTreeNode.setMeta(meta);
			return loginMenuTreeNode;
		}).collect(Collectors.toList());
	}

	@Override
	public List<MenuResVO> listAll(Menu menu) {
		LambdaQueryWrapper<Menu> queryWrapper = Wrappers.<Menu>query().lambda()
				// 根据应用查询
				.eq($.isNotBlank(menu.getApplication()), Menu::getApplication, menu.getApplication())
				// 根据名称模糊查询
				.like($.isNotBlank(menu.getName()), Menu::getName, menu.getName())
				// 查询菜单状态是否为启用
				.eq(Menu::getStatus, StatusType.ENABLE.getCode())
				// 查询排序
				.orderByAsc(Menu::getSort);
		return this.list(queryWrapper).stream().map(m -> {
			MenuResVO menuRes = $.copy(m, MenuResVO.class);
			if ($.isEmpty(menuRes)) {
				return new MenuResVO();
			}
			menuRes.setParentId(m.getPid());
			return menuRes;
		}).collect(Collectors.toList());
	}

	@Override
	public List<MenuTreeResVO> tree(Menu menu) {
		LambdaQueryWrapper<Menu> queryWrapper = Wrappers.<Menu>query().lambda()
				// 根据应用查询
				.eq($.isNotBlank(menu.getApplication()), Menu::getApplication, menu.getApplication())
				// 查询菜单状态是否为启用
				.eq(Menu::getStatus, StatusType.ENABLE.getCode())
				// 查询排序
				.orderByAsc(Menu::getSort);
		return this.list(queryWrapper).stream().map(m -> {
			MenuTreeResVO menuTreeRes = new MenuTreeResVO();
			menuTreeRes.setId(m.getId());
			menuTreeRes.setParentId(m.getPid());
			menuTreeRes.setTitle(m.getName());
			menuTreeRes.setValue($.toStr(m.getId()));
			menuTreeRes.setWeight(m.getWeight());
			return menuTreeRes;
		}).collect(Collectors.toList());
	}

	@Override
	public List<MenuTreeResVO> grantTree(LoginUser user, Menu menu) {

		LambdaQueryWrapper<Menu> queryWrapper = Wrappers.lambdaQuery();
		queryWrapper.eq($.isNotBlank(menu.getApplication()), Menu::getApplication, menu.getApplication());

		if (adminUserChecker.hasModifyPermission(user)) {
			queryWrapper.eq(Menu::getStatus, StatusType.ENABLE.getCode());
		} else {
			Long userId = user.getId();
			List<Long> roleIdList = userRoleService.getUserRoleIdList(userId,UserType.SYSTEM.getType());
			if ($.isNotEmpty(roleIdList)) {
				List<Long> menuIdList = roleMenuService.getRoleMenuIdList(roleIdList);
				if ($.isNotEmpty(menuIdList)) {
					queryWrapper.in(Menu::getId, menuIdList)
							.eq(Menu::getStatus, StatusType.ENABLE.getCode());
				} else {
					//如果角色的菜单为空，则查不到菜单
					return CollectionUtil.newArrayList();
				}
			} else {
				//如果角色为空，则根本没菜单
				return CollectionUtil.newArrayList();
			}
		}
		//根据排序升序排列，序号越小越在前
		queryWrapper.orderByAsc(Menu::getSort);
		return this.list(queryWrapper).stream().map(m -> {
			MenuTreeResVO menuTreeRes = new MenuTreeResVO();
			menuTreeRes.setId(m.getId());
			menuTreeRes.setValue($.toStr(m.getId()));
			menuTreeRes.setTitle(m.getName());
			menuTreeRes.setWeight(m.getWeight());
			menuTreeRes.setParentId(m.getPid());
			return menuTreeRes;
		}).collect(Collectors.toList());
	}

	@Override
	public boolean setMenu(Menu menu) {
		fillHierarchy(menu, menu.getPid());
		return this.saveOrUpdate(menu);
	}

	@Override
	public boolean delMenu(List<Long> ids) {
		ids.forEach(id -> {
			if (this.list(Wrappers.<Menu>lambdaQuery().like(Menu::getHierarchy, StringPool.LEFT_SQ_BRACKET + id + StringPool.RIGHT_SQ_BRACKET)).size() > 0) {
				throw new MarsException(SystemExceptionEnum.SUB_MENU_NOT_DELETE);
			}
			this.removeById(id);
		});
		return Boolean.TRUE;
	}

    private void fillHierarchy(Menu menu, Long pid) {
		if ($.equals(0L, pid)) {
			menu.setHierarchy(StringPool.LEFT_SQ_BRACKET + 0 + StringPool.RIGHT_SQ_BRACKET
					+ StringPool.COMMA);
		} else {
			Menu parentMenu = this.getById(pid);
			menu.setHierarchy(parentMenu.getHierarchy() + StringPool.LEFT_SQ_BRACKET + pid + StringPool.RIGHT_SQ_BRACKET
					+ StringPool.COMMA);
		}
	}
}
